package com.zmn.oms.services.impl.post;

import org.apache.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.common.constant.OrderPostConsts;
import com.zmn.oms.model.entity.post.OrderPost;
import com.zmn.oms.persistence.interfaces.post.OrderPostDao;
import com.zmn.oms.services.interfaces.express.OrderPostService;
import com.zmn.tapi.common.expressage.Expressage;
import com.zmn.tapi.dubbo.interfaces.expressage.ExpressageRemoteService;
import io.shardingsphere.api.HintManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @ClassName OrderPostServiceImpl
 * @Description TODO
 * @Author xiaofei
 * @Date 2020/7/24{TIME}
 * @Version 1.0
 */
@Slf4j
@Service
public class OrderPostServiceImpl implements OrderPostService {
    @Resource
    private OrderPostDao orderPostDao;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ExpressageRemoteService expressageRemoteService;

    /**
     * 根据快递单号和快递公司编码查询订单id
     * @param expressCode
     * @param expressCompanyCode
     * @return java.lang.Long
     * @author wangxiaokun
     */
    @Override
    public Long findOrderIdByExpressCodeAndExpressCompanyCode(String expressCode, String expressCompanyCode){
        return orderPostDao.findOrderIdByExpressCodeAndExpressCompanyCode(expressCode, expressCompanyCode);
    }

    @Override
    public List<OrderPost> listOrderPostByOrderId(Long orderId) {
        List<OrderPost> orderPosts = orderPostDao.listOrderPostByOrderId(orderId);
        if (CollectionUtils.isNotEmpty(orderPosts)) {
            orderPosts.forEach(item -> {
                if (item.getModifiable() == null) {
                    item.setModifiable(GlobalConsts.YES);
                }
                if (item.getSourceType() == null) {
                    item.setSourceType(OrderPostConsts.SOURCE_TYPE_PLATFORM);
                }
            });
        }
        return orderPosts;
    }

    @Override
    public List<OrderPost> listOrderPostByOrderIds(List<Long> orderIdList) {
        try (HintManager hintManager = HintManager.getInstance()) {
            hintManager.setMasterRouteOnly();

            List<OrderPost> orderPosts = orderPostDao.listOrderPostByOrderIds(orderIdList);
            if (CollectionUtils.isNotEmpty(orderPosts)) {
                orderPosts.forEach(item -> {
                    if (item.getModifiable() == null) {
                        item.setModifiable(GlobalConsts.YES);
                    }
                    if (item.getSourceType() == null) {
                        item.setSourceType(OrderPostConsts.SOURCE_TYPE_PLATFORM);
                    }
                });
            }

            return orderPosts;
        }
    }

    @Override
    public int insertOrderPost(OrderPost orderPost) {
        List<OrderPost> unModifiableOrderPosts = listUnModifiableOrderPostByOrderId(orderPost.getOrderId());
        if (CollectionUtils.isNotEmpty(unModifiableOrderPosts)) {
            updateUnModifiableOrderPosts(unModifiableOrderPosts);

            String expressCode = orderPost.getExpressCode();
            for (OrderPost item : unModifiableOrderPosts) {
                if (Objects.equals(expressCode, item.getExpressCode())) {
                    return 0;
                }
            }
        }

        fillExpressInfo(orderPost);
        subscribeExpress(orderPost);

        return orderPostDao.insertOrderPost(orderPost);
    }

    @Override
    public int insertOrderPostList(Long orderId, List<OrderPost> orderPostList) {
        Objects.requireNonNull(orderId);

        List<OrderPost> unModifiableOrderPosts = listUnModifiableOrderPostByOrderId(orderId);
        if (CollectionUtils.isNotEmpty(unModifiableOrderPosts)) {
            updateUnModifiableOrderPosts(unModifiableOrderPosts);

            Map<String, OrderPost> filter = unModifiableOrderPosts.stream()
                    .collect(Collectors.toMap(OrderPost::getExpressCode, Function.identity(), (key1, key2) -> key2));

            List<OrderPost> modifiableOrderPosts = orderPostList.stream()
                    .filter(item -> filter.get(item.getExpressCode()) == null)
                    .collect(Collectors.toList());
            orderPostList = modifiableOrderPosts;
        }

        if (CollectionUtils.isEmpty(orderPostList)) {
            return 0;
        }

        orderPostList.forEach(orderPost -> {
            fillExpressInfo(orderPost);

            orderPost.setOrderId(orderId);
            orderPost.setItemType(OrderPostConsts.EXPRESS_ITEMTYPE_NEW_MACHINE);

//            subscribeExpress(orderPost);
        });

        return orderPostDao.insertOrderPostList(orderPostList);
    }

    @Override
    public int deleteOrderPostByOrderId(Long orderId) {
        return orderPostDao.deleteOrderPostByOrderId(orderId);
    }

    @Override
    public int updateOrderPostExpress(OrderPost orderPost) {
        if (orderPost == null) {
            return 0;
        }
        return orderPostDao.updateOrderPostExpress(orderPost);
    }

    /**
     * 补全邮寄信息
     * @param orderPost
     */
    private void fillExpressInfo(OrderPost orderPost) {
        log.debug("orderPost--->{}", orderPost);
        if (StringUtils.isNotBlank(orderPost.getExpressCompanyCode()) && StringUtil.isBlank(orderPost.getExpressCompany())) {
            // 通过快递公司编号补全快递公司名称
            expressageRemoteService.listCompany().getData().stream().filter(item -> Objects.equals(orderPost.getExpressCompanyCode(), item.getCode())).findFirst().ifPresent(expressageCompany -> orderPost.setExpressCompany(expressageCompany.getName()));
        }
        if (orderPost.getSourceType() == null) {
            orderPost.setSourceType(OrderPostConsts.SOURCE_TYPE_PLATFORM);
        }
        if (orderPost.getModifiable() == null) {
            orderPost.setModifiable(GlobalConsts.YES);
        }

        // 查询快递信息
        ResponseDTO<Expressage> responseExpressage = expressageRemoteService.getExpressageByCompanyAndCode(orderPost.getExpressCompanyCode(), orderPost.getExpressCode());
        log.info("[{}] 查询快递信息：{}", orderPost, responseExpressage);

        if (Objects.nonNull(responseExpressage.getData())) {
            Expressage expressageDRO = responseExpressage.getData();
            orderPost.setStatus(OrderPostConsts.getZmnPostStatus(expressageDRO.getState()));
            if (CollectionUtils.isNotEmpty(expressageDRO.getList())) {
                orderPost.setExpressData(JSON.toJSONString(expressageDRO.getList()));
            }
            orderPost.setValid(GlobalConsts.YES);
        } else {
            orderPost.setValid(GlobalConsts.NO);
        }
    }

    /**
     * 订阅快递单号,实时追踪状态
     */
    private void subscribeExpress(OrderPost orderPost) {
        ResponseDTO responseDTO = expressageRemoteService.subscribe(
                orderPost.getExpressCompanyCode(), orderPost.getExpressCode());
        log.info("[{}] 订阅结果：{}", orderPost, responseDTO.getMessage());
    }

    /**
     * 根据订单号查找不可更改的快递信息
     * @param orderId
     * @return
     */
    private List<OrderPost> listUnModifiableOrderPostByOrderId(Long orderId) {
        return orderPostDao.listUnModifiableOrderPostByOrderId(orderId);
    }

    /**
     * 更新状态限制为不可修改的物流信息（比如渠道物流信息）的实际物流信息
     * @param unModifiableOrderPosts
     * @return
     */
    private int updateUnModifiableOrderPosts(List<OrderPost> unModifiableOrderPosts) {
        int num = 0;
        for (OrderPost item : unModifiableOrderPosts) {
            OrderPost updateModel = new OrderPost();
            updateModel.setExpressId(item.getExpressId());

            // 查询快递信息
            ResponseDTO<Expressage> responseExpressage = expressageRemoteService.getExpressageByCompanyAndCode(
                    item.getExpressCompanyCode(), item.getExpressCode());
            log.info("[{}] 查询快递信息：{}", JSON.toJSONString(item), JSON.toJSONString(responseExpressage));
            if (Objects.nonNull(responseExpressage.getData())) {
                Expressage expressage = responseExpressage.getData();
                updateModel.setStatus(OrderPostConsts.getZmnPostStatus(expressage.getState()));
                if (CollectionUtils.isNotEmpty(expressage.getList())) {
                    updateModel.setExpressData(JSON.toJSONString(expressage.getList()));
                }
                updateModel.setValid(GlobalConsts.YES);

                num += orderPostDao.updateOrderPostExpressById(updateModel);
            }
        }

        return num;
    }
}
